package com.customization.test.demo.util;

import DBstep.iMsgServer2000;
import de.schlichtherle.util.zip.ZipEntry;
import de.schlichtherle.util.zip.ZipOutputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import weaver.conn.ConnStatement;
import weaver.conn.RecordSet;
import weaver.file.AESCoder;
import weaver.general.BaseBean;
import weaver.general.GCONST;
import weaver.general.Util;
import weaver.system.SystemComInfo;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipInputStream;

/**
 * @author sjm
 * @className
 * @description
 * @create 2024-10-21 18:14
 */
public class DownLoadUtils {

    private static BaseBean baseBean = new BaseBean();

    public void doGet(HttpServletRequest request, HttpServletResponse respons) throws IOException {
        RecordSet rsImageFileId = new RecordSet();
        String docids = "";
        // 查询文档
        String sqlImageFileId = "select a.id,a.docsubject,b.imagefileid,b.imagefilename " +
                " from docdetail a, docimagefile b where a.id=b.docid and a.id in (" + docids + ") " +
                " and b.versionId = (select max(c.versionId) from docimagefile c where c.id =b.id) order by a.id asc";
        // 查询附件
        String fileids = "";
        String sqlFile = "select * from imagefile where imagefileid in (" + fileids + ")";
        String docsubject = "";
        rsImageFileId.executeQuery(sqlImageFileId);
        int counts = rsImageFileId.getCounts();
        if (counts <= 0) {

        }
        String docImageFileIds = "";
        int num = 0;
        while (rsImageFileId.next()) {
            num++;
            if (num == counts) {
                docImageFileIds += Util.null2String(rsImageFileId.getString("imagefileid"));
            } else {
                docImageFileIds += Util.null2String(rsImageFileId.getString("imagefileid")) + ",";
            }
            docsubject = Util.null2String(rsImageFileId.getString("docsubject"));
        }

        List<String> fileNameList = new ArrayList<>();
        List<String> fileRealPathList = new ArrayList<>();
        List<String> fileRealPathTempList = new ArrayList<>();

        File fileTemp = null;

        String sqlFileRealPath = "";

        sqlFileRealPath = "select t1.isaesencrypt,t1.aescode,t1.imagefilename,t1.filerealpath,t1.iszip,t1.isencrypt,t1.imagefiletype,t1.imagefileid,t1.imagefile,t2.imagefilename as realname " +
                " from imagefile t1 " +
                " left join docimagefile  t2 " +
                " on t1.imagefileid = t2.imagefileid " +
                " where t1.imagefileid  in (" + docImageFileIds + ")  " + ("".equals(docids) ? "" : "and t2.docid in (" + docids + ")");
        rsImageFileId.executeQuery(sqlFileRealPath);
        while (rsImageFileId.next()) {
            try {
                String imagefileid = Util.null2String(rsImageFileId.getString("imagefileid"));
                String filename = Util.null2String(rsImageFileId.getString("realname"));
                if ("".equals(filename)) {
                    filename = Util.null2String(rsImageFileId.getString("imagefilename"));
                }
                String filerealpath = Util.null2String(rsImageFileId.getString("filerealpath"));
                String iszip = Util.null2String(rsImageFileId.getString("iszip"));
                String isencrypt = Util.null2String(rsImageFileId.getString("isencrypt"));
                String aescode = Util.null2String(rsImageFileId.getString("aescode"));

                /** 文档相关开始*/
                // 流程下载附件，获取最新版本附件下载
                RecordSet rs = new RecordSet();
                String sql = "select doceditionid,id from docdetaill where id (select max(docid) from docimagefile where imagefileid = " + imagefileid + ")";
                rs.executeQuery(sql);
                if (rs.next()) {
                    int doceditionid = rs.getInt("doceditionid");
                    int docid = rs.getInt("id");

                    if (doceditionid > 0) {
                        // 有多版本文件，取最新版本文档
                        sql = "select id from docdetail where doceditionid=" + doceditionid + " order by docedition desc";
                        rs.executeQuery(sql);
                        if (rs.next()) {
                            docid = rs.getInt("id");
                        }
                    }

                    // 在新版本文档取最新附件
                    sql = "select f.imagefileid,f.imagefilename,f.filerealpath,d.imagefilename realname from docimagefile d,imagefile f where d.imagefileid=f.imagefileid and d.docid = " + docid + " orde by d.versionid desc";
                    rs.executeQuery(sql);
                    if (rs.next()) {
                        imagefileid = Util.null2String(rs.getString("imagefileid"));
                        filename = Util.null2String(rs.getString("realname"));
                        if ("".equals(filename)) {
                            filename = Util.null2String(rs.getString("imagefilename"));
                        }
                        filerealpath = Util.null2String(rs.getString("filerealpath"));
                    }

                }
                /** 文档相关结束*/
                fileNameList.add(filename);
                fileRealPathList.add(filerealpath);

                String extName = "";
                if (filename.contains(".")) {
                    int bx = filename.lastIndexOf(".");
                    if (bx >= 0) {
                        extName = filename.substring(bx + 1);
                    }
                }

                int byteread;
                byte[] data = new byte[1024];
                InputStream imagefile = getImageFileInputStreamById(Util.getIntValue(imagefileid));
                if (isOfficeToDocument(extName) && isMsgObjToDocument()) {
                    // 正文的处理
                    ByteArrayOutputStream bout = null;
                    try {

                        bout = new ByteArrayOutputStream();

                        while ((byteread = imagefile.read(data)) != -1) {
                            bout.write(data, 0, byteread);
                            bout.flush();
                        }
                        byte[] fileBody = bout.toByteArray();
                        iMsgServer2000 msgObj = new iMsgServer2000();
                        msgObj.MsgFileBody(fileBody); //将文件信息打包
                        fileBody = msgObj.ToDocument(msgObj.MsgFileBody());

                        imagefile = new ByteArrayInputStream(fileBody);

                        bout.close();

                    } catch (Exception e) {
                        if (bout != null) {
                            try {
                                bout.close();
                            } catch (Exception ex) {

                            }
                        }
                    }
                }

                FileOutputStream out = null;
                try {
                    SystemComInfo comInfo = new SystemComInfo();
                    String fileFoder = comInfo.getFilesystem();

                    if (StringUtils.isNotBlank(fileFoder)) {
                        fileFoder = GCONST.getRootPath();
                        fileFoder = fileFoder+"filesystem"+File.separatorChar+"downloadBatchTemp"+File.separatorChar+"时间"+File.separatorChar;
                    } else {
                        if (fileFoder.endsWith(File.separator)) {
                            fileFoder += "downloadBatchTemp"+File.separatorChar+"时间"+File.separatorChar;
                        } else {
                            fileFoder += File.separator+"downloadBatchTemp"+File.separatorChar+"时间"+File.separatorChar;
                        }
                    }
                    String fileFoderCompare = fileFoder+filename;
                    // 防止附件重名
                    String newFileName = filename;
                    for (String fileRealPathTemp : fileRealPathTempList) {
                        if(fileFoderCompare.equals(fileRealPathTemp)){
                            int lastIndex = filename.lastIndexOf(".");

                            if(lastIndex >= 0){
                                newFileName = filename.substring(0,lastIndex)+"_"+imagefileid+filename.substring(lastIndex);
                            }else {
                                newFileName = filename+imagefileid;
                            }
                        }
                    }

                    fileTemp = fileCreate(fileFoder,newFileName);

                    out = new FileOutputStream(fileTemp);

                    while ((byteread = imagefile.read(data)) != -1) {
                        out.write(data, 0, byteread);
                        out.flush();
                    }
                    fileRealPathTempList.add(fileFoder+newFileName);

                } catch (Exception ex) {

                } finally {
                    if (imagefile != null) {
                        try {
                            imagefile.close();
                        } catch (Exception ex) {

                        }
                    }
                    if (out != null) {
                        try {
                            out.flush();
                        } catch (Exception ex) {

                        }
                    }
                    if (out != null) {
                        try {
                            out.close();
                        } catch (Exception ex) {

                        }
                    }
                }
            } catch (Exception e) {

            }

        }


        // 整合文件，判断是否需要打成压缩包
        int size = fileRealPathTempList.size();
        File[] files = null;
        if(size > 1){
            files = new File[size];
            for (int i = 0; i < size; i++) {
                String fileRealPath = fileRealPathTempList.get(i);
                files[i] = new File(fileRealPath);
            }
        }else if(size == 1){

        }else {

        }

        byte[] bt = new byte[8192];
        SystemComInfo comInfo2 = new SystemComInfo();
        String fileFoder2 = comInfo2.getFilesystem();

        if (StringUtils.isNotBlank(fileFoder2)) {
            fileFoder2 = GCONST.getRootPath();
            fileFoder2 = fileFoder2+"filesystem"+File.separatorChar+"downloadBatch"+File.separatorChar;
        } else {
            if (fileFoder2.endsWith(File.separator)) {
                fileFoder2 += "downloadBatch"+File.separatorChar;
            } else {
                fileFoder2 += File.separator+"downloadBatch"+File.separatorChar;
            }
        }

        // 压缩包命名
        String strs = "";

        String tmpfileName = "时间test.zip";
        File file = fileCreate(fileFoder2, tmpfileName);
        String strzipName = file.getPath();
        String fileTempParent = null;
        if(fileTemp != null){
            fileTempParent = fileTemp.getParent();
        }

        ZipOutputStream zout = null;
        FileInputStream is = null;
        try {
            zout = new ZipOutputStream(new FileOutputStream(strzipName),"UTF-8");

            for (File filez : files) {
                try {
                    is = new FileInputStream(filez);
                    ZipEntry ze = new ZipEntry(filez.getName());
                    zout.putNextEntry(ze);
                    int len;
                    // 读取下载文件内容
                    while ((len = is.read(bt)) > 0){
                        zout.write(bt,0,len);
                    }
                    zout.closeEntry();
                    is.close();
                } catch (Exception e) {

                }
            }

            zout.close();

        } catch (Exception e) {

        }finally {
            if (is != null) {
                try {
                    is.close();
                } catch (Exception ex) {

                }
            }
            if (zout != null) {
                try {
                    zout.close();
                } catch (Exception ex) {

                }
            }

            deleteFile(strzipName);

            if(fileTempParent != null){
                deleteFile(fileTempParent);
            }
        }

    }

    private InputStream getImageFileInputStreamById(int imagefileidOld) {
        InputStream imagefile = null;
        try {
            RecordSet rs = new RecordSet();
            String sql = "select t1.isaesencrypt,t1.aescode,t1.iszip,t1.isencrypt,t1.downloads,t1.miniimgpath,t1.imgsize,t1.isFTP,t1.FTPConfigId,t1.tokenKey,t1.storageStatus,t1.comefrom," +
                    " t1.imagefiletype,t1.imagefilename,t1.imagefileid,t1.imagefileUsed,t1.filesize,t1.filerealpath," +
                    " t2.imagefilename as realname " +
                    " from imagefile t1 " +
                    " left join docimagefile  t2 " +
                    " on t1.imagefileid = t2.imagefileid " +
                    " where t1.imagefileid = " + imagefileidOld;
            rs.executeQuery(sql);
            if (rs.next()) {
                int imagefileid = Util.getIntValue(rs.getString("imagefileid"), 0);
                String filename = Util.null2String(rs.getString("realname"));
                if ("".equals(filename)) {
                    filename = Util.null2String(rs.getString("imagefilename"));
                }
                String filerealpath = Util.null2String(rs.getString("filerealpath"));
                String imagefiletype = Util.null2String(rs.getString("imagefiletype"));
                int imagefileUsed = Util.getIntValue(rs.getString("imagefileUsed"), 0);
                String iszip = Util.null2String(rs.getString("iszip"));
                String isencrypt = Util.null2String(rs.getString("isencrypt"));
                String filesize = Util.null2String(rs.getString("filesize"));
                int downloads = Util.getIntValue(rs.getString("downloads"), 0);
                String miniimgpath = Util.null2String(rs.getString("miniimgpath"));
                int isaesencrypt = Util.getIntValue(rs.getString("isaesencrypt"), 0);
                String aescode = Util.null2String(rs.getString("aescode"));

                if (StringUtils.isNotBlank(filerealpath)) {

                    File theFile = new File(filerealpath);
                    FileInputStream fileInputStream = new FileInputStream(theFile);
                    if ("1".equals(iszip)) {
                        ZipInputStream zin = new ZipInputStream(fileInputStream);
                        if (zin.getNextEntry() != null) {
                            imagefile = new BufferedInputStream(zin);
                        }
                    } else {
                        imagefile = new BufferedInputStream(fileInputStream);
                    }

                } else {
                    ConnStatement statement = null;
                    try {
                        statement = new ConnStatement();
                        boolean isOracle = ("oracle".equals(statement.getDBType()));

                        String sqlQuery = "select imagefile from ImageFile where  imagefileid=" + imagefileid;

                        statement.setStatementSql(sqlQuery);
                        statement.executeQuery();
                        if (statement.next()) {
                            if (isOracle) {
                                imagefile = new BufferedInputStream(statement.getBlobBinary("imagefile"));
                            } else {
                                imagefile = new BufferedInputStream(statement.getBinaryStream("imagefile"));
                            }
                        }

                    } catch (Exception e) {

                    } finally {
                        if (statement != null) {
                            try {
                                statement.close();
                            } catch (Exception e) {

                            }
                        }
                    }
                }

                if (isaesencrypt == 1) {
                    imagefile = AESCoder.decrypt(imagefile, aescode);
                }
            }

        } catch (Exception e) {

        }

        return imagefile;
    }

    private boolean isOfficeToDocument(String extName) {
        boolean isOfficeToDocument = false;
        if ("xls".equalsIgnoreCase(extName) || "doc".equalsIgnoreCase(extName) || "wps".equalsIgnoreCase(extName) || "ppt".equalsIgnoreCase(extName)
                || "docx".equalsIgnoreCase(extName) || "xlsx".equalsIgnoreCase(extName) || "pptx".equalsIgnoreCase(extName)) {
            isOfficeToDocument = true;
        }
        return isOfficeToDocument;
    }

    private boolean isMsgObjToDocument() {
        boolean isMsgObjToDocument = true;
        String iWebOfficeClientName = Util.null2String(baseBean.getPropValue("weaver_obj", "iWebOfficeClientName"));
        boolean isIWebOffice2003 = iWebOfficeClientName.indexOf("iWebOffice2003") > -1 ? true : false;
        String isHandWriteForIWebOffice2009 = Util.null2String(baseBean.getPropValue("weaver_obj", "isHandWriteForIWebOffice2009"));
        if (isIWebOffice2003 || "0".equals(isHandWriteForIWebOffice2009)) {
            isMsgObjToDocument = false;
        }
        return isMsgObjToDocument;
    }

    private File fileCreate(String fileFoder,String newFileName) {
        File foder = new File(fileFoder);
        File file = new File(fileFoder + newFileName);
        if (!foder.exists()){
            foder.mkdirs();
        }
        if(file.exists()){
            try {
                file.delete();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }else {
            try {
                file.createNewFile();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        return file;
    }


    public void downloadFile(HttpServletRequest request, HttpServletResponse response, String fileName, String tmpFileName, String path) {

        InputStream is = null;
        BufferedInputStream bis = null;
        OutputStream os = null;
        BufferedOutputStream bos = null;

        try {

            if (StringUtils.isNotBlank(path)) {
                File file = new File(path);

                if (file.exists()) {
                    is = Files.newInputStream(Paths.get(path));
                    bis = new BufferedInputStream(is);
                    os = response.getOutputStream();
                    bos = new BufferedOutputStream(os);

                    response.setContentType("application/x-download");

                    //获得浏览器代理信息
                    final String userAgent = request.getHeader("USER-AGENT");
                    //判断浏览器代理并分别设置响应给浏览器的编码格式
                    String finalFileName = null;
                    fileName = fileName.replaceAll("<", "").replaceAll(">", "").replaceAll("&lt;", "").replaceAll("&gt;", "");
                    if (StringUtils.contains(userAgent, "MSIE") || StringUtils.contains(userAgent, "Trident")) {//IE浏览器
                        finalFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
                    } else if (StringUtils.contains(userAgent, "Mozilla")) {//google,火狐浏览器
                        finalFileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
                    } else {
                        finalFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");//其他浏览器
                    }
                    response.addHeader("Content-Disposition", "attachment;filename=\"" + finalFileName + "\"");//下载文件的名称

                    // 循环取出流中的数据
                    byte[] buff = new byte[8192];
                    int buffRead;
                    while ((buffRead = bis.read(buff, 0, 8192)) != -1) {
                        bos.write(buff, 0, buffRead);
                    }
                    bos.flush();

                    is.close();
                    bis.close();
                    os.close();
                    bos.close();
                } else {

                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    private void pdFileName(String fileName,int imagefileidOld){
        int byteread;
        byte[] data = new byte[1024];

        RecordSet statement = new RecordSet();
        RecordSet rs = new RecordSet();
        try {

            String sqlQuery =  "select t1.isaesencrypt,t1.aescode,t1.iszip,t1.isencrypt,t1.downloads,t1.miniimgpath,t1.imgsize,t1.isFTP,t1.FTPConfigId,t1.tokenKey,t1.storageStatus,t1.comefrom," +
                    " t1.imagefiletype,t1.imagefilename,t1.imagefileid,t1.imagefileUsed,t1.filesize,t1.filerealpath," +
                    " t2.imagefilename as realname " +
                    " from imagefile t1 " +
                    " left join docimagefile  t2 " +
                    " on t1.imagefileid = t2.imagefileid " +
                    " where t1.imagefileid = " ;

            statement.executeQuery(sqlQuery + imagefileidOld);
            if (statement.next()) {
                String filename = Util.null2String(statement.getString("realname"));
                if ("".equals(filename)) {
                    filename = Util.null2String(statement.getString("imagefilename"));
                }
                String fileNameLowerCase = filename.toLowerCase();
                if(fileNameLowerCase.endsWith(".pdf")){
                    int decryptPdfImageFileId = 0;
                    String sql = "select decryptPdfImageFileId from workflow_texttopdf where pdfImageFileId="+imagefileidOld;
                    rs.executeQuery(sql);
                    if (rs.next()) {
                        decryptPdfImageFileId = Util.getIntValue(statement.getString("decryptPdfImageFileId"), -1);
                    }
                    if(decryptPdfImageFileId > 0){
                        statement.executeQuery(sqlQuery + decryptPdfImageFileId);
                        if (!statement.next()) {
                            return;
                        }
                    }
                }

                String filerealpath = Util.null2String(statement.getString("filerealpath"));
                String iszip = Util.null2String(statement.getString("iszip"));
                String isencrypt = Util.null2String(statement.getString("isencrypt"));
                int isaesencrypt = Util.getIntValue(statement.getString("isaesencrypt"), 0);
                String aescode = Util.null2String(statement.getString("aescode"));
                boolean isHtmlFile = false;
                if(fileNameLowerCase.endsWith(".html") || fileNameLowerCase.endsWith(".htm")) {
                    RecordSet rs_tmp = new RecordSet();

                    rs_tmp.executeQuery("select 1 from DOCpreviewHtml where htmlfileid=?",imagefileidOld);
                    if (rs_tmp.next()) {
                        isHtmlFile = true;
                    }
                }
                String contenttype = "";
                if((!fileNameLowerCase.endsWith(".ppt") && !fileNameLowerCase.endsWith(".pptx") && !fileNameLowerCase.endsWith(".xps") && !fileNameLowerCase.endsWith(".js"))  || isHtmlFile){
                    if(fileNameLowerCase.endsWith(".doc")) {
                        contenttype = "application/msword";
                    }else  if(fileNameLowerCase.endsWith(".xls")) {
                        contenttype = "application/vnd.ms-excel";
                    }else  if(fileNameLowerCase.endsWith(".gif")) {
                        contenttype = "image/gif";
                        //res.addHeader("Cache-Control","private, max-age=8640000");
                    }else  if(fileNameLowerCase.endsWith(".png")) {
                        contenttype = "image/png";
                        //res.addHeader("Cache-Control","private, max-age=8640000");
                    }else  if(fileNameLowerCase.endsWith(".jpg") || fileNameLowerCase.endsWith(".jpeg")) {
                        contenttype = "image/jpg";
                        //res.addHeader("Cache-Control","private, max-age=8640000");
                    }else  if(fileNameLowerCase.endsWith(".bmp")) {
                        contenttype = "image/bmp";
                        // res.addHeader("Cache-Control","private, max-age=8640000");
                    }else  if(fileNameLowerCase.endsWith(".txt")) {
                        contenttype = "text/plain";
                    }else  if(fileNameLowerCase.endsWith(".pdf")) {
                        contenttype = "application/pdf";
                    }else  if(fileNameLowerCase.endsWith(".html") || fileNameLowerCase.endsWith(".htm")) {
                        contenttype = "text/html";
                    }else  {
                        contenttype = "application/msword";
                    }
                }else {
                    contenttype = "application/octet-stream";
                }
            }
        } catch (Exception e) {

        } finally {

        }



    }

    private void deleteFile(String targetPath) throws IOException {
        File targgetFile = new File(targetPath);
        if(targgetFile.isDirectory()){
            if(targetPath.contains("downloadBatchTemp")){
                FileUtils.deleteDirectory(targgetFile);
            }

        }else  if(targgetFile.isFile()){
            targgetFile.delete();
        }

    }
}
